[Boto3 Adv-Cal DAY3]Lightsailインスタンスを対話式で作成するロジックに挑戦してみた
boto3 で楽しむ AWS PythonLife 一人AdventCalendarです。
boto3のドキュメントを通して、サービス別にどういった事が出来るのかを理解したり、管理コンソールを通さずにTerminalだけで完結できるように検証していくことが目的になります。
3日目はLightsailのインスタンスを対話ベースでの作成を試してみました。
目次
boto3を通してLightsailで出来ること
ドキュメントは下記リンク先です。
ざっくりと以下のことができます。
- インスタンスの操作(作成・削除・スナップショット・StaticIP設定)
- ディスクの操作(作成・削除・スナップショット)
- リレーショナル・データベースの操作(作成・削除)
今回の操作
対話ベースでパラメータを指定して、インスタンスを作成します。
- blueprint_idの指定
- bundle_idの指定
- インスタンス名の指定
- リージョンの指定
- インスタンスの作成
dryrun
オプションを指定すると作成は行いません。
% python main.py Input Profile name [default]>>advent_calendar Select blueprint [0] windows_server_2016_2018_10_14 [1] windows_server_2012_2018_10_14 [2] windows_server_2016_sql_2016_express_2018_10_14 [3] amazon_linux_2018_03_0_2 [4] ubuntu_16_04_2 [5] ubuntu_18_04 [6] debian_8_7 [7] debian_9_5 [8] freebsd_11_1 [9] opensuse_42_2 [10] centos_7_1805_01 [11] wordpress_4_9_8 [12] wordpress_multisite_4_9_8 [13] lamp_5_6_37_2 [14] lamp_7_1_20_1 [15] nodejs_10_8_0 [16] joomla_3_8_11 [17] magento_2_2_5 [18] mean_4_0_1 [19] drupal_8_5_6 [20] gitlab_11_1_4_1 [21] redmine_3_4_6 [22] nginx_1_14_0_1 [23] plesk_ubuntu_17_8_11_1 >>3 Select bundle [0] nano_2_0 [1] micro_2_0 [2] small_2_0 [3] medium_2_0 [4] large_2_0 [5] xlarge_2_0 [6] 2xlarge_2_0 [7] nano_win_2_0 [8] micro_win_2_0 [9] small_win_2_0 [10] medium_win_2_0 [11] large_win_2_0 [12] xlarge_win_2_0 [13] 2xlarge_win_2_0 >>0 Input Instance name >>test Select region [0] ap-northeast-1a [1] ap-northeast-1c [2] ap-northeast-1d >>0 test : Started
main.py
import boto3 import subprocess import argparse class LightsailWizard: _client_name = 'lightsail' _session = None def __init__(self, profile_name): self._session = boto3.Session(profile_name=profile_name) @property def session(self): return self._session @property def client(self): return self.session.client(self.client_name) @property def client_name(self): return self._client_name def get_blueprint_ids(self, **kwargs): res = self.client.get_blueprints(**kwargs) return [blueprint['blueprintId'] for blueprint in res['blueprints']] def get_bundle_ids(self, **kwargs): res = self.client.get_bundles(**kwargs) return [bundle['bundleId'] for bundle in res['bundles']] def get_regions(self, **kwargs): kwargs.update({'includeAvailabilityZones':True}) res = self.client.get_regions(**kwargs) zone_names = list() for region in res['regions']: for zone in region['availabilityZones']: zone_names.append(zone['zoneName']) return zone_names def create_instance(self, instance_name, availability_zone, blueprint_id, bundle_id): params = { 'instanceNames': [instance_name], 'availabilityZone': availability_zone, 'blueprintId': blueprint_id, 'bundleId': bundle_id } lightsail = self.client res = lightsail.create_instances(**params) for ope in res['operations']: print("{name} : {status}".format(name=ope['resourceName'], status=ope['status'])) @classmethod def prompt_instance_name(cls): instance_name = None while True: instance_name = input('Input Instance name >>') if instance_name and len(instance_name) != 0: break return instance_name def prompt_availability_zone(self): region_name = None while True: print('\nSelect region') region_names = self.get_regions() for region_name in region_names: print('[{}] {}'.format(region_names.index(region_name), region_name)) index = input('>> ') if len(index) != 0 and int(index) < len(region_names): region_name = region_names[int(index)] break return region_name def prompt_blueprint(self): blueprint_id = None while True: print('\nSelect blueprint') blueprint_ids = self.get_blueprint_ids() for blueprint_id in blueprint_ids: print('[{}] {}'.format(blueprint_ids.index(blueprint_id), blueprint_id)) index = input('>> ') if len(index) != 0 and int(index) < len(blueprint_ids): blueprint_id = blueprint_ids[int(index)] break return blueprint_id def prompt_bundle(self): bundle_id = None while True: print('\nSelect bundle') bundle_ids = self.get_bundle_ids() for bundle_id in bundle_ids: print('[{}] {}'.format(bundle_ids.index(bundle_id), bundle_id)) index = input('>> ') if len(index) != 0 and int(index) < len(bundle_ids): bundle_id = bundle_ids[int(index)] break return bundle_id @staticmethod def prompt(dryrun=True): if dryrun: print("dryrun-mode") params = {} default_profile_name = 'default' profile_name = input('Input Profile name [{}]>> '.format(default_profile_name)) if len(profile_name) == 0: profile_name = default_profile_name wizard = LightsailWizard(profile_name) blueprint_id = wizard.prompt_blueprint() bundle_id = wizard.prompt_bundle() instance_name = wizard.prompt_instance_name() region_name = wizard.prompt_availability_zone() if dryrun: result_format = "instance_name: {}, region_name: {}, blueprint_id: {}, bundle_id: {}" print(result_format.format(instance_name, region_name, blueprint_id, bundle_id)) return wizard.create_instance(instance_name, region_name, blueprint_id, bundle_id) if __name__ == '__main__': parser = argparse.ArgumentParser() parser.add_argument('--dryrun', action='store_true') args = parser.parse_args() LightsailWizard.prompt(args.dryrun)
get_region
インスタンス生成時に必要なリージョン名取得はincludeAvailabilityZones=True
の指定が必要です。
まとめ
Lightsail用のコマンドを通して、お手軽インスタンス生成のロジックを組んでみました。細かいパラメータを指定できるようにすると、色々と対応可能な幅も広がると思います。
なお、今回のロジックはインスタンスを作成するだけで削除しません。作成したインスタンスが必要なければ忘れずに削除しておきましょう。